home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Games / MAME / src / vidhrdw / atarisy2.c < prev    next >
C/C++ Source or Header  |  2000-05-18  |  16KB  |  600 lines

  1. /***************************************************************************
  2.  
  3.     Atari System 2 hardware
  4.  
  5. ****************************************************************************/
  6.  
  7.  
  8. #include "driver.h"
  9. #include "machine/atarigen.h"
  10. #include "vidhrdw/generic.h"
  11.  
  12. #define XCHARS 64
  13. #define YCHARS 48
  14.  
  15. #define XDIM (XCHARS*8)
  16. #define YDIM (YCHARS*8)
  17.  
  18.  
  19.  
  20. /*************************************
  21.  *
  22.  *    Constants
  23.  *
  24.  *************************************/
  25.  
  26. #define PFRAM_SIZE        0x4000
  27. #define ANRAM_SIZE        0x1800
  28. #define MORAM_SIZE        0x0800
  29.  
  30.  
  31.  
  32. /*************************************
  33.  *
  34.  *    Structures
  35.  *
  36.  *************************************/
  37.  
  38. struct mo_data
  39. {
  40.     struct osd_bitmap *bitmap;
  41.     int xhold;
  42. };
  43.  
  44.  
  45. struct pf_overrender_data
  46. {
  47.     struct osd_bitmap *bitmap;
  48.     int mo_priority;
  49. };
  50.  
  51.  
  52.  
  53. /*************************************
  54.  *
  55.  *    Globals we own
  56.  *
  57.  *************************************/
  58.  
  59. UINT8 *atarisys2_slapstic;
  60.  
  61.  
  62.  
  63. /*************************************
  64.  *
  65.  *    Statics
  66.  *
  67.  *************************************/
  68.  
  69. static UINT8 *playfieldram;
  70. static UINT8 *alpharam;
  71.  
  72. static UINT8 videobank;
  73.  
  74. static struct atarigen_pf_state pf_state;
  75. static UINT16 latched_vscroll;
  76.  
  77.  
  78.  
  79. /*************************************
  80.  *
  81.  *    Prototypes
  82.  *
  83.  *************************************/
  84.  
  85. static void pf_render_callback(const struct rectangle *clip, const struct rectangle *tiles, const struct atarigen_pf_state *state, void *data);
  86. static void pf_check_overrender_callback(const struct rectangle *clip, const struct rectangle *tiles, const struct atarigen_pf_state *state, void *data);
  87. static void pf_overrender_callback(const struct rectangle *clip, const struct rectangle *tiles, const struct atarigen_pf_state *state, void *data);
  88.  
  89. static void mo_render_callback(const UINT16 *data, const struct rectangle *clip, void *param);
  90.  
  91.  
  92.  
  93. /*************************************
  94.  *
  95.  *    Video system start
  96.  *
  97.  *************************************/
  98.  
  99. int atarisys2_vh_start(void)
  100. {
  101.     static struct atarigen_mo_desc mo_desc =
  102.     {
  103.         256,                 /* maximum number of MO's */
  104.         8,                   /* number of bytes per MO entry */
  105.         2,                   /* number of bytes between MO words */
  106.         3,                   /* ignore an entry if this word == 0xffff */
  107.         3, 3, 0xff,          /* link = (data[linkword] >> linkshift) & linkmask */
  108.         0                    /* render in reverse link order */
  109.     };
  110.  
  111.     static struct atarigen_pf_desc pf_desc =
  112.     {
  113.         8, 8,                /* width/height of each tile */
  114.         128, 64                /* number of tiles in each direction */
  115.     };
  116.  
  117.     /* allocate banked memory */
  118.     alpharam = calloc(0x8000, 1);
  119.     if (!alpharam)
  120.         return 1;
  121.  
  122.     spriteram = alpharam + ANRAM_SIZE;
  123.     playfieldram = alpharam + 0x4000;
  124.  
  125.     /* reset the videoram banking */
  126.     videoram = alpharam;
  127.     videobank = 0;
  128.  
  129.     /*
  130.      * if we are palette reducing, do the simple thing by marking everything used except for
  131.      * the transparent sprite and alpha colors; this should give some leeway for machines
  132.      * that can't give up all 256 colors
  133.      */
  134.     if (palette_used_colors)
  135.     {
  136.         int i;
  137.         memset(palette_used_colors, PALETTE_COLOR_USED, Machine->drv->total_colors * sizeof(UINT8));
  138.         for (i = 0; i < 4; i++)
  139.             palette_used_colors[15 + i * 16] = PALETTE_COLOR_TRANSPARENT;
  140.         for (i = 0; i < 8; i++)
  141.             palette_used_colors[64 + i * 4] = PALETTE_COLOR_TRANSPARENT;
  142.     }
  143.  
  144.     /* initialize the playfield */
  145.     if (atarigen_pf_init(&pf_desc))
  146.     {
  147.         free(alpharam);
  148.         return 1;
  149.     }
  150.  
  151.     /* initialize the motion objects */
  152.     if (atarigen_mo_init(&mo_desc))
  153.     {
  154.         atarigen_pf_free();
  155.         free(alpharam);
  156.         return 1;
  157.     }
  158.  
  159.     return 0;
  160. }
  161.  
  162.  
  163.  
  164. /*************************************
  165.  *
  166.  *    Video system shutdown
  167.  *
  168.  *************************************/
  169.  
  170. void atarisys2_vh_stop(void)
  171. {
  172.     /* free memory */
  173.     if (alpharam)
  174.         free(alpharam);
  175.     alpharam = playfieldram = spriteram = 0;
  176.  
  177.     atarigen_pf_free();
  178.     atarigen_mo_free();
  179. }
  180.  
  181.  
  182.  
  183. /*************************************
  184.  *
  185.  *    Scroll/playfield bank write
  186.  *
  187.  *************************************/
  188.  
  189. WRITE_HANDLER( atarisys2_hscroll_w )
  190. {
  191.     int oldword = READ_WORD(&atarigen_hscroll[offset]);
  192.     int newword = COMBINE_WORD(oldword, data);
  193.     WRITE_WORD(&atarigen_hscroll[offset], newword);
  194.  
  195.     /* update the playfield parameters - hscroll is clocked on the following scanline */
  196.     pf_state.hscroll = (newword >> 6) & 0x03ff;
  197.     pf_state.param[0] = newword & 0x000f;
  198.     atarigen_pf_update(&pf_state, cpu_getscanline() + 1);
  199.  
  200.     /* mark the playfield dirty for those games that handle it */
  201.     if (oldword != newword && (Machine->drv->video_attributes & VIDEO_SUPPORTS_DIRTY))
  202.         osd_mark_dirty(Machine->drv->visible_area.min_x, Machine->drv->visible_area.min_y,
  203.                         Machine->drv->visible_area.max_x, Machine->drv->visible_area.max_y, 0);
  204. }
  205.  
  206.  
  207. WRITE_HANDLER( atarisys2_vscroll_w )
  208. {
  209.     int oldword = READ_WORD(&atarigen_vscroll[offset]);
  210.     int newword = COMBINE_WORD(oldword, data);
  211.     WRITE_WORD(&atarigen_vscroll[offset], newword);
  212.  
  213.     /* if bit 4 is zero, the scroll value is clocked in right away */
  214.     latched_vscroll = (newword >> 6) & 0x01ff;
  215.     if (!(newword & 0x10)) pf_state.vscroll = latched_vscroll;
  216.  
  217.     /* update the playfield parameters */
  218.     pf_state.param[1] = newword & 0x000f;
  219.     atarigen_pf_update(&pf_state, cpu_getscanline() + 1);
  220.  
  221.     /* mark the playfield dirty for those games that handle it */
  222.     if (oldword != newword && (Machine->drv->video_attributes & VIDEO_SUPPORTS_DIRTY))
  223.         osd_mark_dirty(Machine->drv->visible_area.min_x, Machine->drv->visible_area.min_y,
  224.                         Machine->drv->visible_area.max_x, Machine->drv->visible_area.max_y, 0);
  225. }
  226.  
  227.  
  228.  
  229. /*************************************
  230.  *
  231.  *    Palette RAM write handler
  232.  *
  233.  *************************************/
  234.  
  235. WRITE_HANDLER( atarisys2_paletteram_w )
  236. {
  237.     static const int intensity_table[16] =
  238.     {
  239.         #define ZB 115
  240.         #define Z3 78
  241.         #define Z2 37
  242.         #define Z1 17
  243.         #define Z0 9
  244.         0, ZB+Z0, ZB+Z1, ZB+Z1+Z0, ZB+Z2, ZB+Z2+Z0, ZB+Z2+Z1, ZB+Z2+Z1+Z0,
  245.         ZB+Z3, ZB+Z3+Z0, ZB+Z3+Z1, ZB+Z3+Z1+Z0,ZB+ Z3+Z2, ZB+Z3+Z2+Z0, ZB+Z3+Z2+Z1, ZB+Z3+Z2+Z1+Z0
  246.     };
  247.     static const int color_table[16] =
  248.         { 0x0, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xe, 0xf, 0xf };
  249.  
  250.     int inten, red, green, blue;
  251.  
  252.     int oldword = READ_WORD(&paletteram[offset]);
  253.     int newword = COMBINE_WORD(oldword, data);
  254.     int indx = offset / 2;
  255.  
  256.     WRITE_WORD(&paletteram[offset], newword);
  257.  
  258.     inten = intensity_table[newword & 15];
  259.     red = (color_table[(newword >> 12) & 15] * inten) >> 4;
  260.     green = (color_table[(newword >> 8) & 15] * inten) >> 4;
  261.     blue = (color_table[(newword >> 4) & 15] * inten) >> 4;
  262.     palette_change_color(indx, red, green, blue);
  263. }
  264.  
  265.  
  266.  
  267. /*************************************
  268.  *
  269.  *    Video RAM bank read/write handlers
  270.  *
  271.  *************************************/
  272.  
  273. READ_HANDLER( atarisys2_slapstic_r )
  274. {
  275.     slapstic_tweak(offset / 2);
  276.  
  277.     /* an extra tweak for the next opcode fetch */
  278.     videobank = slapstic_tweak(0x1234);
  279.     videoram = alpharam + videobank * 0x2000;
  280.  
  281.     return READ_WORD(&atarisys2_slapstic[offset]);
  282. }
  283.  
  284.  
  285. WRITE_HANDLER( atarisys2_slapstic_w )
  286. {
  287.     slapstic_tweak(offset / 2);
  288.  
  289.     /* an extra tweak for the next opcode fetch */
  290.     videobank = slapstic_tweak(0x1234);
  291.     videoram = alpharam + videobank * 0x2000;
  292. }
  293.  
  294.  
  295.  
  296. /*************************************
  297.  *
  298.  *    Video RAM read/write handlers
  299.  *
  300.  *************************************/
  301.  
  302. READ_HANDLER( atarisys2_videoram_r )
  303. {
  304.     return READ_WORD(&videoram[offset]);
  305. }
  306.  
  307.  
  308. WRITE_HANDLER( atarisys2_videoram_w )
  309. {
  310.     int oldword = READ_WORD(&videoram[offset]);
  311.     int newword = COMBINE_WORD(oldword, data);
  312.     WRITE_WORD(&videoram[offset], newword);
  313.  
  314.     /* mark the playfield dirty if we write to it */
  315.     if (videobank >= 2)
  316.         if ((oldword & 0x3fff) != (newword & 0x3fff))
  317.         {
  318.             int offs = (&videoram[offset] - playfieldram) / 2;
  319.             atarigen_pf_dirty[offs] = 0xff;
  320.         }
  321.  
  322.     /* force an update if the link of object 0 changes */
  323.     if (videobank == 0 && offset == 0x1806)
  324.         atarigen_mo_update(spriteram, 0, cpu_getscanline() + 1);
  325. }
  326.  
  327.  
  328.  
  329. /*************************************
  330.  *
  331.  *    Periodic scanline updater
  332.  *
  333.  *************************************/
  334.  
  335. void atarisys2_scanline_update(int scanline)
  336. {
  337.     /* update the playfield */
  338.     if (scanline == 0)
  339.     {
  340.         pf_state.vscroll = latched_vscroll;
  341.         atarigen_pf_update(&pf_state, scanline);
  342.     }
  343.  
  344.     /* update the motion objects */
  345.     if (scanline < YDIM)
  346.         atarigen_mo_update(spriteram, 0, scanline);
  347. }
  348.  
  349.  
  350.  
  351. /*************************************
  352.  *
  353.  *    Main refresh
  354.  *
  355.  *************************************/
  356.  
  357. void atarisys2_vh_screenrefresh(struct osd_bitmap *bitmap, int full_refresh)
  358. {
  359.     struct mo_data modata;
  360.     int i;
  361.  
  362.     /* recalc the palette if necessary */
  363.     if (palette_recalc())
  364.         memset(atarigen_pf_dirty, 0xff, PFRAM_SIZE / 2);
  365.  
  366.     /* set up the all-transparent overrender palette */
  367.     for (i = 0; i < 16; i++)
  368.         atarigen_overrender_colortable[i] = palette_transparent_pen;
  369.  
  370.     /* render the playfield */
  371.     atarigen_pf_process(pf_render_callback, bitmap, &Machine->drv->visible_area);
  372.  
  373.     /* render the motion objects */
  374.     modata.xhold = 0;
  375.     modata.bitmap = bitmap;
  376.     atarigen_mo_process(mo_render_callback, &modata);
  377.  
  378.     /* render the alpha layer */
  379.     {
  380.         const struct GfxElement *gfx = Machine->gfx[2];
  381.         int sx, sy, offs;
  382.  
  383.         for (sy = 0; sy < YCHARS; sy++)
  384.             for (sx = 0, offs = sy * 64; sx < XCHARS; sx++, offs++)
  385.             {
  386.                 int data = READ_WORD(&alpharam[offs * 2]);
  387.                 int code = data & 0x3ff;
  388.  
  389.                 /* if there's a non-zero code, draw the tile */
  390.                 if (code)
  391.                 {
  392.                     int color = (data >> 13) & 7;
  393.  
  394.                     /* draw the character */
  395.                     drawgfx(bitmap, gfx, code, color, 0, 0, 8 * sx, 8 * sy, 0, TRANSPARENCY_PEN, 0);
  396.                 }
  397.             }
  398.     }
  399.  
  400.     /* update onscreen messages */
  401.     atarigen_update_messages();
  402. }
  403.  
  404.  
  405.  
  406. /*************************************
  407.  *
  408.  *    Playfield rendering
  409.  *
  410.  *************************************/
  411.  
  412. static void pf_render_callback(const struct rectangle *clip, const struct rectangle *tiles, const struct atarigen_pf_state *state, void *param)
  413. {
  414.     const struct GfxElement *gfx = Machine->gfx[0];
  415.     struct osd_bitmap *bitmap = param;
  416.     int x, y;
  417.  
  418.     /* standard loop over tiles */
  419.     for (y = tiles->min_y; y != tiles->max_y; y = (y + 1) & 63)
  420.         for (x = tiles->min_x; x != tiles->max_x; x = (x + 1) & 127)
  421.         {
  422.             int offs = y * 128 + x;
  423.             int data = READ_WORD(&playfieldram[offs * 2]);
  424.             int pfbank = state->param[(data >> 10) & 1];
  425.  
  426.             /* update only if dirty */
  427.             if (atarigen_pf_dirty[offs] != pfbank)
  428.             {
  429.                 int code = (pfbank << 10) + (data & 0x3ff);
  430.                 int color = (data >> 11) & 7;
  431.  
  432.                 drawgfx(atarigen_pf_bitmap, gfx, code, color, 0, 0, 8 * x, 8 * y, 0, TRANSPARENCY_NONE, 0);
  433.                 atarigen_pf_dirty[offs] = pfbank;
  434.             }
  435.         }
  436.  
  437.     /* then blast the result */
  438.     x = -state->hscroll;
  439.     y = -state->vscroll;
  440.     copyscrollbitmap(bitmap, atarigen_pf_bitmap, 1, &x, 1, &y, clip, TRANSPARENCY_NONE, 0);
  441. }
  442.  
  443.  
  444.  
  445. /*************************************
  446.  *
  447.  *    Playfield overrender check
  448.  *
  449.  *************************************/
  450.  
  451. static void pf_check_overrender_callback(const struct rectangle *clip, const struct rectangle *tiles, const struct atarigen_pf_state *state, void *param)
  452. {
  453.     struct pf_overrender_data *overrender_data = param;
  454.     const struct GfxElement *gfx = Machine->gfx[0];
  455.     int mo_priority = overrender_data->mo_priority;
  456.     int x, y;
  457.  
  458.     /* if we've already decided, bail */
  459.     if (mo_priority == -1)
  460.         return;
  461.  
  462.     /* standard loop over tiles */
  463.     for (y = tiles->min_y; y != tiles->max_y; y = (y + 1) & 63)
  464.         for (x = tiles->min_x; x != tiles->max_x; x = (x + 1) & 127)
  465.         {
  466.             int offs = y * 128 + x;
  467.             int data = READ_WORD(&playfieldram[offs * 2]);
  468.             int pf_priority = ((~data >> 13) & 6) | 1;
  469.  
  470.             if ((mo_priority + pf_priority) & 4)
  471.             {
  472.                 int pfbank = state->param[(data >> 10) & 1];
  473.                 int code = (pfbank << 10) + (data & 0x3ff);
  474.                 if (gfx->pen_usage[code] & 0xff00)
  475.                 {
  476.                     overrender_data->mo_priority = -1;
  477.                     return;
  478.                 }
  479.             }
  480.         }
  481. }
  482.  
  483.  
  484.  
  485. /*************************************
  486.  *
  487.  *    Playfield overrendering
  488.  *
  489.  *************************************/
  490.  
  491. static void pf_overrender_callback(const struct rectangle *clip, const struct rectangle *tiles, const struct atarigen_pf_state *state, void *param)
  492. {
  493.     const struct pf_overrender_data *overrender_data = param;
  494.     const struct GfxElement *gfx = Machine->gfx[0];
  495.     struct osd_bitmap *bitmap = overrender_data->bitmap;
  496.     int mo_priority = overrender_data->mo_priority;
  497.     int x, y;
  498.  
  499.     /* standard loop over tiles */
  500.     for (y = tiles->min_y; y != tiles->max_y; y = (y + 1) & 63)
  501.     {
  502.         int sy = (8 * y - state->vscroll) & 0x1ff;
  503.         if (sy >= YDIM) sy -= 0x200;
  504.  
  505.         for (x = tiles->min_x; x != tiles->max_x; x = (x + 1) & 127)
  506.         {
  507.             int offs = y * 128 + x;
  508.             int data = READ_WORD(&playfieldram[offs * 2]);
  509.             int pf_priority = ((~data >> 13) & 6) | 1;
  510.  
  511.             if ((mo_priority + pf_priority) & 4)
  512.             {
  513.                 int pfbank = state->param[(data >> 10) & 1];
  514.                 int code = (pfbank << 10) + (data & 0x3ff);
  515.                 int color = (data >> 11) & 7;
  516.                 int sx = (8 * x - state->hscroll) & 0x1ff;
  517.                 if (sx >= XDIM) sx -= 0x400;
  518.  
  519.                 drawgfx(bitmap, gfx, code, color, 0, 0, sx, sy, clip, TRANSPARENCY_PENS, 0x00ff);
  520.             }
  521.         }
  522.     }
  523. }
  524.  
  525.  
  526.  
  527. /*************************************
  528.  *
  529.  *    Motion object rendering
  530.  *
  531.  *************************************/
  532.  
  533. static void mo_render_callback(const UINT16 *data, const struct rectangle *clip, void *param)
  534. {
  535.     struct GfxElement *gfx = Machine->gfx[1];
  536.     struct mo_data *modata = param;
  537.     struct osd_bitmap *bitmap = modata->bitmap;
  538.     struct pf_overrender_data overrender_data;
  539.     struct rectangle pf_clip;
  540.  
  541.     /* extract data from the various words */
  542.     int ypos = -(data[0] >> 6);
  543.     int hold = data[1] & 0x8000;
  544.     int hflip = data[1] & 0x4000;
  545.     int vsize = ((data[1] >> 11) & 7) + 1;
  546.     int code = (data[1] & 0x7ff) + ((data[0] & 7) << 11);
  547.     int xpos = (data[2] >> 6);
  548.     int color = (data[3] >> 12) & 3;
  549.     int priority = (data[3] >> 13) & 6;
  550.  
  551.     /* adjust for height */
  552.     ypos -= vsize * 16;
  553.  
  554.     /* adjust x position for holding */
  555.     if (hold)
  556.         xpos = modata->xhold;
  557.     modata->xhold = xpos + 16;
  558.  
  559.     /* adjust the final coordinates */
  560.     xpos &= 0x3ff;
  561.     ypos &= 0x1ff;
  562.     if (xpos >= XDIM) xpos -= 0x400;
  563.     if (ypos >= YDIM) ypos -= 0x200;
  564.  
  565.     /* clip the X coordinate */
  566.     if (xpos <= -16 || xpos >= XDIM)
  567.         return;
  568.  
  569.     /* determine the bounding box */
  570.     atarigen_mo_compute_clip_16x16(pf_clip, xpos, ypos, 1, vsize, clip);
  571.  
  572.     /* determine if we need to overrender */
  573.     overrender_data.mo_priority = priority;
  574.     atarigen_pf_process(pf_check_overrender_callback, &overrender_data, &pf_clip);
  575.  
  576.     /* if not, do it simply */
  577.     if (overrender_data.mo_priority == priority)
  578.     {
  579.         atarigen_mo_draw_16x16_strip(bitmap, gfx, code, color, hflip, 0, xpos, ypos, vsize, clip, TRANSPARENCY_PEN, 15);
  580.     }
  581.  
  582.     /* otherwise, make it tricky */
  583.     else
  584.     {
  585.         /* draw an instance of the object in all transparent pens */
  586.         atarigen_mo_draw_transparent_16x16_strip(bitmap, gfx, code, hflip, 0, xpos, ypos, vsize, clip, TRANSPARENCY_PEN, 15);
  587.  
  588.         /* and then draw it normally on the temp bitmap */
  589.         atarigen_mo_draw_16x16_strip(atarigen_pf_overrender_bitmap, gfx, code, color, hflip, 0, xpos, ypos, vsize, clip, TRANSPARENCY_NONE, 0);
  590.  
  591.         /* overrender the playfield on top of that that */
  592.         overrender_data.mo_priority = priority;
  593.         overrender_data.bitmap = atarigen_pf_overrender_bitmap;
  594.         atarigen_pf_process(pf_overrender_callback, &overrender_data, &pf_clip);
  595.  
  596.         /* finally, copy this chunk to the real bitmap */
  597.         copybitmap(bitmap, atarigen_pf_overrender_bitmap, 0, 0, 0, 0, &pf_clip, TRANSPARENCY_THROUGH, palette_transparent_pen);
  598.     }
  599. }
  600.